/*
* 这个程序要实现贝叶斯分类 使用之前已经生成的字典
*
* author：fuxiang ，fuxiang90@gmail.com

*/

# include<stdio.h>
# include<string.h>
# include<iostream>
#include<string>
#include<vector>
#include <map>
#include <fstream>
#include <ext/hash_map>
#include <iomanip>
using namespace std ;

const int N = 5;
map<string ,double > bMap[N]; /*  每个分类一个map*/
map<string ,int > dictMap;
vector<int > result_bayes[2];
long count_classify[N] ;




void getDictMap()
{

    ifstream infile("dict.txt");
    if(!infile)
    {
        cout <<  "dict open error "<<endl;
    }
    string word;
    int i = 1;
    while(infile >>  word)
    {
        dictMap.insert(map<string ,int >::value_type( word, i));
        //i ++ ;
        //cout << word <<endl;
    }
}
int insertMap(string word ,int type )
{
    map<string ,double >::iterator iter = bMap[type].find(word);
    if(iter  != bMap[type].end() )
    {
        iter->second += 1.0;
    }
    else
        bMap[type].insert(map<string ,double >::value_type(word,1.0)) ;

    count_classify[type] ++ ;
    return 1;
}
void bayes()
{
    ifstream infile("train.txt");
    //ifstream input;
    if(!infile)
    {
        cout <<  "train open error "<<endl;
    }
    string word;
    string filename;
    char *temp = (char *)malloc(sizeof(char)  * 10) ;
    int i = 1;
    int type;

    /*这一步  是统计每一分类 ，他每个单词出现的次数*/
    while(infile >>  filename)
    {
        strcpy(temp,filename.c_str()) ;
        type = temp[0] - '0' ;
        ifstream input( filename.c_str() );
        if( ! input)
            cout << filename << " open error" << endl;
        map<string ,int >::iterator iter  ;
        while(input >> word)
        {
            string rc = word.substr(0,word.find("/")) ;

            if(dictMap.find(rc) != dictMap.end())
                insertMap(rc,type-1);

            //cout << word  <<endl;
        }
        memset(temp,0,10 * sizeof(char));
        input.close();
    }
    infile.close();
    /*计算 P（Wk| Vj） ,
    因为我各自分类取的文档数是一定的所以 我的p（Vj） = 1/N */
    for(type = 0 ; type < N ; type ++ )
    {
        long sizeInt = bMap[type].size();
        map<string ,double >::iterator iter ;
        for(iter =bMap[type].begin() ; iter != bMap[type].end() ; iter ++ )
        {
            iter->second = (iter->second + 1.0)/(sizeInt + count_classify[type]) ;

            //cout << iter->second << endl;
        }
    }

}

int findMax(double data[])
{
    int i = 0,max = 0;
    for(i =1 ; i < N ; i ++)
    {
        if(data[i] > data[max])
            max = i ;
    }
    return max;
}
/*  对待分类文档进行分类*/
void classifyBayes()
{
    double result[N] ;
    int i ;
    int type;


    ifstream infile("test.txt");
    //ifstream input;
    if(!infile)
    {
        cout <<  "open error "<<endl;
    }
    string word;
    string filename;
    char *temp = (char *)malloc(sizeof(char)  * 20) ;
    while(infile >>  filename)
    {
        strcpy(temp,filename.c_str()) ;
        type = temp[0] - '0'  ;
        result_bayes[0].push_back(type -1 );
        ifstream input( filename.c_str() );

        //cout << filename << endl ;

        if( !input)
            cout << filename << " open error" << endl;
        map<string ,double >::iterator iter  ;
        while(input >> word)
        {
            string rc = word.substr(0,word.find("/")) ;
            //cout << rc << endl;
            for(i = 0 ; i < N ; i ++)
            {
                iter = bMap[i].find(rc);
                if( iter  != bMap[i].end())
                    result[i] += iter->second;
            }

        }
        memset(temp,0,20 * sizeof(char));
        //cout << filename << endl ;
        result_bayes[1].push_back(findMax(result));
        memset(result,0,sizeof(result));
        input.close();
    }
    infile.close();

    cout << "ok" ;
}

void print()
{
    int len = result_bayes[0].size();
    int yes = 0;
    for(int i = 0 ; i < len ; i ++)
    {
        if( result_bayes[0][i] == result_bayes[1][i] )
            yes ++ ;
    }
    printf("所有分类的正确率：%.6lf\n",yes*1.0/len);

}

 void printf_map()
 {
     for(int type = 0 ; type < N ; type ++ )
    {
        long sizeInt = bMap[type].size();
        map<string ,double >::iterator iter ;
        for(iter =bMap[type].begin() ; iter != bMap[type].end() ; iter ++ )
        {
            cout << iter->second << endl;
        }
        cout << "-------------------------------------------------" <<endl << endl ;
    }
 }
int main()
{
    getDictMap();
    bayes();
    classifyBayes();
    print();
    //printf_map();
   // getchar();
    return 0;
}

